; 7ch 中断模拟loop指令 在屏幕中间显示80个！

assume cs:code, ds:data, ss:stack

data segment
data ends

stack segment stack
    db 32 dup(0)
stack ends

code segment

start:
    mov ax, stack

    mov sp, 32

    call initReg

    ; 复制指令到指定胡内存位置

    call functionToMemory

    call setInterruptFlag

    mov cx, 80

    mov bp, 160*12

    ; loop 指令 是标号地址 - loop指令的第一个字节
    mov bx, OFFSET startDisplay - endDisplay

startDisplay:
    call displayString

    int 7CH ;  
endDisplay:

    mov ax, 4c00H

    int 21H

; 设置中断标志
setInterruptFlag:

    mov word ptr es:[7CH * 4], 7E00H

    mov es:[7CH * 4 + 2], es

    ret

displayString:
   
    push es

    mov ax, 0b800H

    mov es, ax

    

    mov si, 0


    mov byte ptr es:[bp], '!'

    add bp, 2

    pop es   

    ret

;
instructionsStart:
    ; ss =>  push bp  push ip push cs pushf

    dec cx
    jcxz jumpOut

    push bp

    mov bp, sp

    ; 修改栈中 ip 地址偏移寄存器
    add ss:[bp + 2], bx

    pop bp
jumpOut:    

    iret    ; 出栈
instructionsEnd:
    nop

functionToMemory:

    push ds

    mov ax, cs

    mov ds, ax
    ; 开始复制的位置
    mov si,  OFFSET instructionsStart
    
    ; 总共复制多少字节
    mov cx, OFFSET instructionsEnd - instructionsStart

    ; 复制到es内存中的哪个位置
    mov di, 7E00H

    cld

    rep movsb

    pop ds
    ret

; 初始化
initReg:
    mov ax, data

    mov ds, ax

    mov ax, 0

    mov es, ax
   
    ret


code ends

end start